package com.luanhj.framework.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.luanhj.framework.tenant.TenantContext;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@EnableTransactionManagement(proxyTargetClass = true)
@Configuration
public class MybatisPlusConfig {
    @Autowired
    private TenantLineInnerInterceptor tenantLineInnerInterceptor;
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor()
    {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 添加多租户插件：TenantLineInnerInterceptor
        if (tenantLineInnerInterceptor != null) {
            interceptor.addInnerInterceptor(tenantLineInnerInterceptor);
        }

        // 分页插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor());
        // 乐观锁插件
        interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor());
        // 阻断插件
        interceptor.addInnerInterceptor(blockAttackInnerInterceptor());
        return interceptor;
    }

    /**
     * 创建并配置多租户拦截器
     * 该方法用于初始化一个 TenantLineInnerInterceptor 实例，通过匿名内部类重写 TenantLineHandler 接口
     * 主要作用是在 SQL 执行前，自动加上租户 ID 条件，以实现数据隔离
     *
     * @return 配置好的 TenantLineInnerInterceptor 实例，用于 MyBatis Plus 的多租户支持
     */

    // public TenantLineInnerInterceptor tenantLineInnerInterceptor() {
    //     TenantLineInnerInterceptor tenantLineInnerInterceptor = new TenantLineInnerInterceptor(new TenantLineHandler() {
    //
    //         /**
    //          * 获取当前请求的租户 ID（tenant_id），用于拼接到 SQL 查询条件中
    //          * 通过 TenantContext 上下文工具类获取线程绑定的租户标识
    //          *
    //
    //          * @return 表达式形式的 tenant_id 值，供 MyBatis Plus 拼接 SQL 使用
    //          */
    //         @Override
    //         public Expression getTenantId() {
    //             String tenantId = TenantContext.getTenantId();
    //             //SQL 中字符串字段需要加单引号，因此构造为 'tenantId'。
    //             return new StringValue("'" + tenantId + "'");
    //         }
    //
    //         /**
    //          * 判断是否忽略当前表的多租户条件
    //          * 可用于排除系统级表（如 tenants 租户信息表）不进行租户隔离
    //          * @param tableName 当前操作的数据表名
    //          * @return true 表示忽略该表的租户条件，false 表示应用租户条件
    //          */
    //         @Override
    //         public boolean ignoreTable(String tableName) {
    //             // 忽略 "tenant" 表，避免死循环或系统表误操作
    //             return "tenant".equalsIgnoreCase(tableName);
    //         }
    //     });
    //
    //     return tenantLineInnerInterceptor;
    // }


    /**
     * 分页插件，自动识别数据库类型 https://baomidou.com/guide/interceptor-pagination.html
     */
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        // 设置数据库类型为mysql
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 设置最大单页限制数量，默认 500 条，-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        return paginationInnerInterceptor;
    }

    /**
     * 乐观锁插件 https://baomidou.com/guide/interceptor-optimistic-locker.html
     */
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
        return new OptimisticLockerInnerInterceptor();
    }

    /**
     * 如果是对全表的删除或更新操作，就会终止该操作 https://baomidou.com/guide/interceptor-block-attack.html
     */
    public BlockAttackInnerInterceptor blockAttackInnerInterceptor(){
        return new BlockAttackInnerInterceptor();
    }
}
